Skip to content

fix(agent): stop inheriting superseded parent session denies in subagents - #45064

Closed
leoncheng57 wants to merge 1 commit into
anomalyco:devfrom
leoncheng57:fix/subagent-effective-deny-inheritance
Closed

fix(agent): stop inheriting superseded parent session denies in subagents#45064
leoncheng57 wants to merge 1 commit into
anomalyco:devfrom
leoncheng57:fix/subagent-effective-deny-inheritance

Conversation

@leoncheng57

@leoncheng57 leoncheng57 commented Aug 25, 2026

Copy link
Copy Markdown

Issue for this PR

Closes #45078

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Session permission rules are append-only and evaluated last-match-wins, but deriveSubagentSessionPermission copies every parent-session deny into a task subagent, ignoring rule order. A parent whose rule history is [bash deny, bash allow] is effectively allowed — clients that implement plan-style restrictions append denies and later restore with allows, since PATCH is append-only — yet every new task child receives only the stale bash deny and is permanently blocked from bash even when its own agent policy allows it.

The fix filters the copied denies down to the parent's effective ceiling: a deny is dropped when a later rule targets the identical (permission, pattern) pair, because last-match-wins means that later rule, not the deny, is the parent's effective action for that key. This is deliberately conservative for partial overrides — a later allow with a different pattern (e.g. bash "git *" after bash "*" deny) does not drop the broad deny, so the inherited ceiling never widens beyond what the parent's own evaluation permits for the copied rule's exact pattern. external_directory inheritance and the default todowrite/task denies are unchanged, and the existing hard-ceiling behavior ([bash deny] alone still binds the child) is preserved.

How did you verify your code works?

  • Added three tests to test/agent/plan-mode-subagent-bypass.test.ts (the suite that already exercises this production helper): a re-allowed deny is not inherited, a partially-overridden deny still is, and re-allowing one permission does not drop unrelated denies. bun test test/agent → 52 pass.
  • bun test test/permission-task.test.ts test/session → 433 pass, 0 fail; tsgo --noEmit clean.
  • Live end-to-end on a 1.18.22 deployment with this commit cherry-picked: a parent with appended [bash deny, bash allow] spawned a task child whose session ruleset contained no bash deny, and the child completed a bash command. Stock 1.18.22 reproduces the stale inherited deny.

Screenshots / recordings

Not a UI change.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

@github-actions github-actions Bot added needs:compliance This means the issue will auto-close after 2 hours. needs:issue labels Aug 25, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Thanks for your contribution!

This PR doesn't have a linked issue. All PRs must reference an existing issue.

Please:

  1. Open an issue describing the bug/feature (if one doesn't exist)
  2. Add Fixes #<number> or Closes #<number> to this PR description

See CONTRIBUTING.md for details.

@github-actions

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

Based on my search, I found one potentially related PR:

PR #42174: fix(core): subagent sessions inherit ancestor deny rules
#42174

This appears to be directly related to PR #45064 as it addresses subagent session deny rule inheritance. PR #42174 likely implements the foundational mechanism that PR #45064 is now fixing (to prevent superseded denies from being inherited).

@leoncheng57

Copy link
Copy Markdown
Author

Verified end-to-end on a live 1.18.22 deployment with this commit cherry-picked: a parent session with appended [bash deny, bash allow] history spawned a task subagent whose session ruleset contained no inherited bash deny, and the child completed a bash command normally. Stock 1.18.22 reproduces the stale inherited deny.

@github-actions

Copy link
Copy Markdown
Contributor

Thanks for updating your PR! It now meets our contributing guidelines. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Task subagents inherit parent session denies that later rules superseded

1 participant